Profitability of slot machines in a casino
Should the casino increase or decrease slot machine “prices”?
casino <- read.csv ("casino.csv" )
slot_number month days_active hold denomination location coin_in
1 1 1 28 9.84 0.25 J 69090.45
2 1 2 31 9.84 0.25 J 73333.34
3 1 3 27 8.52 0.25 J 63591.55
4 1 4 31 8.52 0.25 J 84263.49
5 1 5 30 9.84 0.25 J 92990.34
6 1 6 31 9.84 0.25 J 67822.66
slot_number month days_active hold
Min. : 1 Min. : 1.000 Min. : 1.0 Min. : 4.25
1st Qu.: 701 1st Qu.: 5.000 1st Qu.:30.0 1st Qu.: 7.53
Median :1217 Median : 8.000 Median :31.0 Median : 9.99
Mean :1189 Mean : 8.526 Mean :29.9 Mean :10.15
3rd Qu.:1743 3rd Qu.:13.000 3rd Qu.:31.0 3rd Qu.:12.43
Max. :2401 Max. :16.000 Max. :31.0 Max. :16.75
denomination location coin_in
Min. : 0.050 Length:30439 Min. : 303
1st Qu.: 0.250 Class :character 1st Qu.: 47062
Median : 0.250 Mode :character Median : 77301
Mean : 0.956 Mean : 117583
3rd Qu.: 1.000 3rd Qu.: 137849
Max. :100.000 Max. :5111112
Some useful observations from the data:
2,401 slot machine observed over a range of 16 months
The average slot machine has been active for 29.9 days in a given month. As low as 1 day a month and as high as 31 days.
The mean hold is 10.15 with a standard deviation of 2.63, and it varies from 4.25 to 16.75
There are 20 locations.
The average revenue per month for a slot machine is $117,582.57. As low as $303.03, as high as $5,111,112.00.
What is the total revenue of the casino chain over the 16 month period?
sum (casino$ coin_in * casino$ hold/ 100 )
Demand Model
What is price in this data?
There are no explicit prices. The hold of the casino can be considered to be like a price.
The hold is the (long-run) average proportion of the bets that the casino keeps.
Profit
If:
\(Q\) is the volume of play (referred to as coin_ins by the industry)
\(h\) is the hold and \(c\) is the marginal cost
Profits of the casino are:
But \(c\) of a casino is very close to zero
Without any marginal costs, we can decide to raise or lower prices from the price elasticity estimate alone
Demand Model
There is variation in the number of days for which the machine is active.
coin-ins will naturally be higher for a machine that is active for more days.
Using coin_in itself can give misleading results.
Create a new variable Qdaily, which is:
the ratio of coin_ins and days_active
casino$ Qdaily <- casino$ coin_in/ casino$ days_active
Model building
Will the data be useful for modeling slot machine demand?
We need variation in holds in order to run a regression analysis for this purpose
We always need variation in the IV and DV!
How can we check this?
Model building
Will the data be useful for modeling slot machine demand?
We need variation in holds in order to run a regression analysis for this purpose
We always need variation in the IV and DV!
How can we check this?
Scatter plot of Qdaily vs. hold
ggplot (data = casino, aes ( x = hold, y = Qdaily)) +
geom_point () +
theme_classic ()
What is the relationship?
Is it linear or is it more “curved”?
There seems to be a downward sloping effect of holds on coin_ins
The relationship does not appear to be linear
Very small hold: coin_ins high
A multiplicative/log-linear demand model is likely to be a better fit to these data.
Simple demand model specification
Now we can use Qdaily as our demand variable and our demand model can be written as:
\(log(Qdaily) = \beta_0 + \beta_1 \times log(hold) + e\)
in R:
lm1 <- lm (log (Qdaily) ~ log (hold), data = casino)
Simple demand model specification
Call:
lm(formula = log(Qdaily) ~ log(hold), data = casino)
Residuals:
Min 1Q Median 3Q Max
-5.6346 -0.4141 0.0156 0.4780 3.2330
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 10.96853 0.03555 308.52 <2e-16 ***
log(hold) -1.34687 0.01547 -87.05 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.7674 on 30437 degrees of freedom
Multiple R-squared: 0.1993, Adjusted R-squared: 0.1993
F-statistic: 7578 on 1 and 30437 DF, p-value: < 2.2e-16
Interpret the coefficient for hold – What does this imply for raising or lowering hold percentages?
This elasticity estimate suggests that the demand is elastic
The casino should decrease holds to increase revenues/profits
It suggests that consumers are aware of and very responsive to holds.
What concerns might you have for the validity of this?
If we have omitted variables, then we can bias our estimates of price elasticities
Prediction tasks
Let’s predict Qdaily when hold <- 2
logQ_predict <- predict (lm1, newdata = data.frame ( hold = 2 ))
How do we take this out of log() form?
Prediction tasks
How do we take this out of log() form?
It would be nice if this worked:
But it doesn’t. Why?
In lm(), we assume that the average error is 0
Not the sum of squared error
When we log-transform and exponentiate, it’s actually \(e^{\frac{\sigma^2}{2}}\)
Where \(\sigma^2\) is the standard error of the log-linear regression model
Prediction tasks
How do we take this out of log() form?
When we log-transform and exponentiate, avg error = \(e^{\frac{\sigma^2}{2}}\)
This means that \(\frac{\sigma^2}{2}\) is included in our prediction:
\(Q = e^{a-\eta log(P)+\frac{\sigma^2}{2}}\)
If we just type exp( predict(...)), we get \(Q = e^{a-\eta log(P)}\)
And underestimate demand
The fix is somewhat easy
Prediction tasks
How do we take this out of log() form?
\(Q = e^{a-\eta log(P)+\frac{\sigma^2}{2}}\)
exp (logQ_predict + sigma (lm1) ^ 2 / 2 )
sigma(lm1) is the standard error of lm1 (\(\sigma\) )
Prediction tasks
Confusing… I know. Just remember:
# Same as always
logQ_predict <- predict (lm1, newdata = data.frame ( hold = 2 ))
# Take it out of log
Q_predict <- exp (logQ_predict + sigma (lm1) ^ 2 / 2 )
What is our prediction?
Controlling for slot denominations
We have information on slot denominations in the data.
Should we include that information in our analysis?
Do denominations affect the volume of coin-ins?
Likely. Consumers who use high-denomination slot machines are likely systematically different.
Are slot denominations potentially correlated with holds?
Controlling for slot denominations
Generate a scatter plot of demonination vs. hold:
ggplot (data = casino, aes ( x = factor (denomination), y = hold)) +
geom_point () +
theme_classic ()
Controlling for slot denominations
lm2 <- lm (log (Qdaily) ~ log (hold) + factor (denomination), data = casino)
summary (lm2)
Call:
lm(formula = log(Qdaily) ~ log(hold) + factor(denomination),
data = casino)
Residuals:
Min 1Q Median 3Q Max
-6.0291 -0.3731 0.0387 0.4546 2.1024
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.96298 0.05725 174.039 < 2e-16 ***
log(hold) -0.66380 0.02121 -31.292 < 2e-16 ***
factor(denomination)0.25 -0.73884 0.02428 -30.429 < 2e-16 ***
factor(denomination)0.5 -0.67726 0.02819 -24.026 < 2e-16 ***
factor(denomination)1 -0.35017 0.02635 -13.289 < 2e-16 ***
factor(denomination)2 -0.22966 0.04725 -4.860 1.18e-06 ***
factor(denomination)5 0.33564 0.03555 9.442 < 2e-16 ***
factor(denomination)10 0.58851 0.05921 9.939 < 2e-16 ***
factor(denomination)25 0.71686 0.07777 9.218 < 2e-16 ***
factor(denomination)100 1.46711 0.11262 13.026 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.7286 on 30429 degrees of freedom
Multiple R-squared: 0.2784, Adjusted R-squared: 0.2781
F-statistic: 1304 on 9 and 30429 DF, p-value: < 2.2e-16
Interpret the coefficient for hold
The coefficient estimate imples a 1% increase in price corresponds to a 0.66% decrease in demand. – What does this estimate imply for the casino?
Thus, the casino could gain in profitability by raising rather than lowering holds – Which model (lm1 or lm2) do you have greater confidence in? Why?
In light of lm2 using stronger controls, we will tend to have higher confidence in model lm2
If you want more practice
There is also location (location) and time (month) information.
Practice with adding those if you want more.
Price optimization
With inelastic demand, predicted profits increase forever as prices increase.
This emphasizes the role of price constraints — Statistical reliability of model decreases when proposed prices are very different from prices in the data.
In the case of inelastic demand, “optimal” price will generally be the maximum price considered under the constraints.
In practice, managerial reaction should be to raise prices by a “reasonably large” amount (e.g. ~10-15%)
After demand data is collected using the new prices, the demand model should be re-estimated.
This process should be repeated until demand estimates are elastic, at which point truly optimal prices may be calculated.
Price optimization
Although we have inelastic demand in this case, we can still demonstrate the graphical approach to determining optimal prices
To do this, we will:
Create an R function to evaluate casino profits, given predictors and an lm() model
Evaluate profits over a range of holds (prices), and plot the results.
Price optimization
Create a function called casino_pft()
Inputs: – hold - hold percentage – month - month of observation – denomination - denomination of slot machine – location - location of slot machine – lm_result - log-linear model estimation results (lm output)
Output: – Q - predicted demand (daily coin-ins) – profit - predicted profit
Price optimization
Create a function called casino_pft()
casino_pft <- function (hold, month, denomination, location, lm_result) {
# DF that we will use to make predictions
pred_DF = data.frame ( month = month,
hold = hold,
denomination = denomination,
location = location)
logQ = predict (lm_result, newdata= pred_DF) #Predict log value
Q = exp (logQ+ sigma (lm_result)^ 2 / 2 ) #Fix it!
profit = Q* hold/ 100
return (list (Q = Q, profit = profit))
}
Price optimization
Use your casino_pft() to evaluate casino profits for:
hold: hold percentages ranging from 10 to 20 (percent)
month = 1
denomination = 1
location = “B”
lm_result = lm3
Where lm3:
lm3 <- lm (log (Qdaily) ~ log (hold) + month + factor (denomination) + factor (location), data = casino)
Price optimization
Create data.frame to hold results:
results <- data.frame (
holds = 10 : 20 ,
pft = rep (0 ,length (10 : 20 ))
)
Calculate and plot!
for (i in 1 : nrow (results)) {
results$ pft[i] <- casino_pft (hold = results$ hold[i],
month = 1 ,
denomination = 1 ,
location = "B" ,
lm_result = lm3)$ profit
}
ggplot (data = results,
aes ( x = holds, y = pft)) +
geom_point () +
theme_classic ()
Discussion
What does the plot imply for the optimal pricing for the specified slot machine?
The plot demonstrates that “optimal” profits occur at the maximum hold evaluated (20). In the case of elastic demand, such methods can be used to find optimal profits that do not occur at constraint boundaries.
Pricing and Demand for Multiple Products
Pricing and Demand for Multiple Products
Recall from last class: The multiplicative demand model
\(log(Q_i) = \beta_0 + \beta_1\times log(P_i)\)
This is often too simple
Does not account for competing products
But we can generalize it to allow for the effect of competing product prices
Pricing and Demand for Multiple Products
Single product:
\(log(Q_i) = \beta_0 + \beta_1\times log(P_i)\)
Multiple products:
\(log(Q_i) = \beta_{i0} + \beta_{i1}\times log(P_{i}) + \beta_{i2}\times log(P_{2})\)
\(log(Q_1) = \beta_{10} + \beta_{11}\times log(P_{1}) + \beta_{12}\times log(P_{2})\)
\(log(Q_2) = \beta_{20} + \beta_{21}\times log(P_{1}) + \beta_{22}\times log(P_{2})\)
The price coefficients have two subscripts
The first subscript refers to the equation
i.e. demand function for product \(i\)
The second refers to the specific product/competitor
Pricing and Demand for Multiple Products
\(log(Q_1) = \beta_{10} + \beta_{11}\times log(P_{1}) + \beta_{12}\times log(P_{2})\)
\(log(Q_2) = \beta_{20} + \beta_{21}\times log(P_{1}) + \beta_{22}\times log(P_{2})\)
This means that:
\(\beta_{10}\) is the \(log\) of unit sales of Product 1 when \(log(P_1) == 0\) & \(log(P_2) == 0\)
\(\beta_{20}\) is the \(log\) of unit sales of Product 2 when \(log(P_1) == 0\) & \(log(P_2) == 0\)
\(\beta_{11}\) is the…?
Own price elasticity of Product 1
\(\beta_{21}\) is the own price elasticity of Product 2
How much the sales of a product change when its own price changes
\(\beta_{12}\) is the…?
Cross price elasticity of Product 2 on Product 1
How much the sales of a product change when its competitor’s price changes
Pricing and Demand for Multiple Products
The coefficients in these equations are price elasticities, just as in the simple multiplicative demand model discussed before:
\(\beta_{ik} = \frac{\%\triangle Q_i}{\%\triangle P_k}\)
Own and cross price elasticities
Own price elasticities are typically negative
When the price of something increases, all else equal , sales fall
This is why we expected \(\beta_1\) to be negative in the single product case
Cross-price elasticities can be positive or negative
When/why?
Positive when products are substitutes for one another
(e.g. Coke vs. Pepsi)
Price of Coke increases, people switch to Pepsi
Negative when products are compliments for one another
Implications of large cross-price elasticities
When price elasticity is large and positive :
Competitor’s product with high cross price elasticity?
Competitive price change will have a large impact on the demand for our product
Price competition will be tough — Low equilibrium prices
Product in our own product line with high price elasticity?
Cannibalization of sales from other products in our product line
Need to manage the prices of all products in product line simultaneously
Implications of large cross-price elasticities
When price elasticity is large and negative :
Competitor’s product with low cross price elasticity (< -2)?
Price change will have a large impact on the demand for our product
Tough spot to be in–can’t collude on prices
e.g., video games and consoles
Product in our own product line with low cross price elasticity (< -2)?
Probably parts of a set
e.g., battery and charger
Need to manage the prices of all products in product line simultaneously
Potentially sell in bundles?
Implications of small cross-price elasticities
Product with low cross price elasticity?
Price change will have a small impact on the demand for our product
Products may not be true substitutes
e.g., Kashi cereal and Cookie Crisp
Price competition will not be tough — Higher equilibrium prices
How can we get to this point?
Advertising–make our product seem different
e.g., Gasoline, cell phone carriers, insurance providers, etc.
If both products are ours, we could create optimally different products
e.g., combine with a conjoint analysis
Predicting changes in demand
To predict change in demand, we can use the change in prices:
\(log(Q_1) = \beta_{10} + \beta_{11}\times log(P_{1}) + \beta_{12}\times log(P_{2})\)
Came from: \(Q_1 = A^{\beta_{10}} P_1^{\beta_{11}}P_2^{\beta_{12}}\)
This was gross, but we can use it again:
\(\frac{Q'_1}{Q_1} = \frac{A^{\beta_{10}}P{'}_{12}^{\beta_{11}}P{'}_2^{\beta_{12}}}{A^{\beta_{10}}P_1^{\beta_{11}}P_2^{\beta_{12}}}\)
\(P{'}_{i} = P_i\times (1 + \triangle P_i)\)
\(\frac{Q'_1}{Q_1} = \frac{A^{\beta_{10}}P_1\times (1 + \triangle P_1)^{\beta_{11}}P_2\times (1 + \triangle P_2)^{\beta_{12}}}{A^{\beta_{10}}P_1^{\beta_{11}}P_2^{\beta_{12}}}\)
\(\frac{Q'_1}{Q_1} = \frac{P_1\times (1 + \triangle P_1)^{\beta_{11}}P_2\times (1 + \triangle P_2)^{\beta_{12}}}{P_1^{\beta_{11}}P_2^{\beta_{12}}}\)
\(\frac{Q'_1}{Q_1} = (1 + \triangle P_i)^{\beta_{11}}(1 + \triangle P_i)^{\beta_{12}}\)
Predicting changes in demand
To predict change in demand, we can use the change in prices:
\(\frac{Q'_1}{Q_1} = (1 + \triangle P_i)^{\beta_{11}}(1 + \triangle P_i)^{\beta_{12}}\)
Or, in R:
change_in_Q1 <- (1 + change_in_P1) ^ beta11 * (1 + change_in_P2) ^ beta12
Workshop
We’ve got data about three cereals:
Frosted Flakes
Froot Loops
Kashi GoLean Crunch
Read in the data:
data <- read.csv ("cereals_demand.csv" )
Estimate
Demand for Froot Loops: Single-Product Case
\(log(Q_{fl}) = \beta_{0} + \beta_{1}\times log(P_{fl})\)
fl_single <- lm ( data = data, log (sales_fl) ~ log (price_fl))
summary (fl_single)$ coef |> round (3 )
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.006 0.534 16.858 0
log(price_fl) -1.134 0.270 -4.195 0
Conclusions
Demand for Froot Loops: Single-Product Case
What is the own-price elasticity?
-1.134
1% increase in price reduces sales by 1.134%
Don’t increase prices!! Reduce them!
Look at the \(R^2\) from this model. What is it?
~14%
We explain 14% of the variation in sales with Froot Loop prices alone
Can we do better?
Estimate
Demand for Froot Loops: Multiple-Product Case
\(log(Q_{fl}) = \beta_{fl0} + \beta_{fl1}\times log(P_{fl}) + \beta_{fl2}\times log(P_{ff}) + \beta_{fl3}\times log(P_{k})\)
fl_multiple <- lm ( data = data, log (sales_fl) ~ log (price_fl) + log (price_ff) + log (price_k))
summary (fl_multiple)$ coef |> round (3 )
Estimate Std. Error t value Pr(>|t|)
(Intercept) 6.323 0.867 7.291 0.000
log(price_fl) -1.605 0.262 -6.124 0.000
log(price_ff) 1.255 0.223 5.637 0.000
log(price_k) 0.566 0.279 2.029 0.045
Conclusions
Demand for Froot Loops: Multiple-Product Case
What is the own-price elasticity?
-1.6
1% increase in price reduces sales by 1.6%
Don’t increase prices!! Reduce them!
Conclusions
Demand for Froot Loops: Multiple-Product Case
What is cross-price elasticity?
Frosted Flakes:
1.3
Frosted flakes prices impact us a lot!
Their price increases, our sales do too
Kashi:
.6
Kashi prices don’t impact a lot
Their price increases, our sales do too
Not as competitive though
Conclusions
Demand for Froot Loops: Multiple-Product Case
What is \(R^2\) ?
.362
We explain 14% of the variation in sales with all prices
With those around you:
Repeat this for Frosted flakes and Kashi
Estimate single and multiple product demand models
Note differences in elasticities
And \(R^2\)
Estimate
Demand for Frosted Flakes: Single-Product Case
ff_single <- lm ( data = data, log (sales_ff) ~ log (price_ff))
summary (ff_single)$ coef |> round (3 )
Estimate Std. Error t value Pr(>|t|)
(Intercept) 8.782 0.665 13.213 0.000
log(price_ff) -1.239 0.345 -3.590 0.001
Conclusions
Demand for Frosted Flakes: Single-Product Case
What is the own-price elasticity?
-1.24
1% increase in price reduces sales by 1.24%
Don’t increase prices!! Reduce them!
Look at the \(R^2\) from this model. What is it?
Estimate
Demand for Frosted Flakes: Multiple-Product Case
ff_multiple <- lm ( data = data, log (sales_ff) ~ log (price_fl) + log (price_ff) + log (price_k))
summary (ff_multiple)$ coef |> round (3 )
Estimate Std. Error t value Pr(>|t|)
(Intercept) 6.248 1.417 4.411 0.000
log(price_fl) 1.326 0.428 3.098 0.003
log(price_ff) -1.674 0.364 -4.603 0.000
log(price_k) 0.355 0.456 0.779 0.438
Conclusions
Demand for Frosted Flakes: Multiple-Product Case
What is the own-price elasticity?
-1.3
1% increase in price reduces sales by 1.3%
Don’t increase prices!! Reduce them!
Conclusions
Demand for Frosted Flakes: Multiple-Product Case
What is cross-price elasticity?
Kashi:
.35
Prices don’t impact us a lot
Froot loops:
Conclusions
Demand for Frosted Flakes: Multiple-Product Case
What is \(R^2\) ?
.19
We explain 19% of the variation in sales with all prices
Estimate
Demand for Kashi: Single-Product Case
k_single <- lm ( data = data, log (sales_k) ~ log (price_k))
summary (k_single)$ coef |> round (3 )
Estimate Std. Error t value Pr(>|t|)
(Intercept) 7.126 0.377 18.914 0
log(price_k) -1.502 0.178 -8.446 0
Conclusions
Demand for Kashi: Single-Product Case
What is the own-price elasticity?
-1.5
1% increase in price reduces sales by 1.5%
Don’t increase prices!! Reduce them!
Look at the \(R^2\) from this model. What is it?
Estimate
Demand for Kashi: Multiple-Product Case
k_multiple <- lm ( data = data, log (sales_k) ~ log (price_fl) + log (price_ff) + log (price_k))
summary (k_multiple)$ coef |> round (3 )
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.704 0.539 10.579 0.000
log(price_fl) 0.336 0.163 2.060 0.042
log(price_ff) 0.265 0.138 1.917 0.058
log(price_k) -1.384 0.173 -7.980 0.000
Conclusions
Demand for Kashi: Multiple-Product Case
What is the own-price elasticity?
-1.4
1% increase in price reduces sales by 1.4%
Don’t increase prices!! Reduce them!
Conclusions
Demand for Kashi: Multiple-Product Case
What is cross-price elasticity?
Frosted Flakes:
.27
Frosted flakes prices don’t impact us a lot
Froot loops:
.34
Froot loops prices don’t impact a lot
Conclusions
Demand for Kashi: Multiple-Product Case
What is \(R^2\) ?
.47
We explain 47% of the variation in sales with all prices
Change in prices
Now assume that:
Froot Loops increases its price by 5%
Kashi reduces its price by 15%
Calculate the percentage change in demand for each of the three products
Repeat this for the other two products
Frosted Flakes
beta_ff_fl <- ff_multiple$ coefficients[[2 ]]
beta_ff_ff <- ff_multiple$ coefficients[[3 ]]
beta_ff_k <- ff_multiple$ coefficients[[4 ]]
ff_ratio <- (1 + change_in_fl) ^ beta_ff_fl * (1 + change_in_ff) ^ beta_ff_ff * (1 + change_in_k) ^ beta_ff_k
ff_ratio
ff_pct <- 100 * (ff_ratio-1 )
ff_pct
Kashi
beta_k_fl <- k_multiple$ coefficients[[2 ]]
beta_k_ff <- k_multiple$ coefficients[[3 ]]
beta_k_k <- k_multiple$ coefficients[[4 ]]
k_ratio <- (1 + change_in_fl) ^ beta_k_fl * (1 + change_in_ff) ^ beta_k_ff * (1 + change_in_k) ^ beta_k_k
k_ratio
k_pct <- 100 * (k_ratio-1 )
k_pct
Estimated Profit
Assume that the base prices of three products are:
FL = $2.99
FF = $3.25
K = $4.99
And base sales levels are:
FL = 566
FF = 540
K = 302
Assuming the same percentage price changes, what do we expect i) demand and ii) profits for each product at the new prices to be?
Conclusions
We can use demand models to predict demand for single products, as well as multiple.
Adding parameters for other products allows us to estimate demand in a competitive landscape.
We use these models (rather than conjoint) when we have observational data about sales and product attributes
Price is one attribute. We could have done this with others.
Conclusions
Elasticities > 0 indicate as attribute increases, so do sales
Elasticities < 0 indicate as attribute increases, sales decrease
Elasticities < -1 indicate that we should decrease prices, as sales will increase more to make up
We could have extended this example a lot , to simulate profits, entire markets, etc.